package com.csw.shuanfa.CodeImprove.exercise.future;

import com.csw.shuanfa.utils.ThreadPoolUtil;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 不论Future.get()方法还是CompletableFuture.get()方法都是阻塞的，为了获取任务的结果同时不阻塞当前线程的执行，我们可以使用CompletionStage提供的方法结合callback来实现任务的异步处理。
 * <p>
 * ##whenComplete：是执行当前任务的线程执行继续执行 whenComplete 的任务。
 * ##whenCompleteAsync：把 whenCompleteAsync 这个任务继续提交给线程池来进行执行，也就是并行执行。
 * <p>
 * ##thenApply：当一个线程依赖另一个线程时，可以使用 thenApply 方法来把这两个线程串行化
 * <p>
 * ##thenAccept：thenAccept接收上一阶段的输出作为本阶段的输入，并消费处理，无返回结果。
 * <p>
 * ##thenRun：不关心前一阶段的计算结果，因为它不需要输入参数，进行消费处理，无返回结果。
 * <p>
 * ## thenCombine：会把两个 CompletionStage 的任务都执行完成后，把两个任务的结果一块交给 thenCombine 来处理。
 * <p>
 * ## applyToEither ：两个CompletionStage，谁执行返回的结果快，我就用那个CompletionStage的结果进行下一步的转化操作。
 * <p>
 * ##acceptEither 方法：两个CompletionStage，谁执行返回的结果快，我就用那个CompletionStage的结果进行下一步的消耗操作
 * -----------------------------------
 * ©著作权归作者所有：来自51CTO博客作者fourier_的原创作品，请联系作者获取转载授权，否则将追究法律责任
 * future.get方法阻塞问题的解决，实现按照任务完成的先后顺序获取任务的结果
 * https://blog.51cto.com/u_12856592/6129255
 * CompletableFuture<Void> allFutures2 = CompletableFuture.allOf(future1,future2);
 * CompletableFuture<Void> allFutures2 = CompletableFuture.allOf(futureList.toArray(new CompletableFuture[0]));
 */
public class CompletableFutureDemo01 {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService threadPool = ThreadPoolUtil.getExecutorServiceCPU();

        //测试两个线程池会不会有影响
        ExecutorService threadPool2 = ThreadPoolUtil.getExecutorServiceCPU();
        if (threadPool.isShutdown() == true) {
            if (threadPool2.isShutdown() == false) {
                threadPool2.shutdownNow();
            }
        }


        try {
            List<CompletableFuture> futureList = new ArrayList<>();

            CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> {
                System.out.println("执行无返回结果的异步任务");
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }, threadPool);
            futureList.add(future1);

            CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
                System.out.println("执行有返回值的异步任务");
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return "Hello World";
            }, threadPool);
            futureList.add(future2);
            CompletableFuture.allOf(futureList.toArray(futureList.toArray(new CompletableFuture[0]))).get(1, TimeUnit.SECONDS);
            //CompletableFuture.allOf(future1, future2, future3, future4, future5, future6, future7).get(1, TimeUnit.SECONDS);


        } catch (Exception e) {
            threadPool.shutdown();
            throw new RuntimeException(e);
        }

    }
}